<template>
  <div class="hello">
    <div class="dynamic-bg"></div>
    <div class="game-content">
      <h1>{{ msg }}</h1>
      <div class="game-controls">
        <button @click="startGame" class="game-button">开始游戏</button>
        <button @click="resetGame" class="game-button">重置游戏</button>
      </div>
      <div class="game-board-container">
        <div class="game-board" @keydown="handleKeydown" tabindex="0">
          <div 
            v-for="(number, index) in numbers" 
            :key="index" 
            class="number-cell" 
            :class="['number-' + number, { 'moving': isMoving(index) }]"
            :style="getCellStyle(index)"
          >
            {{ number }}
          </div>
        </div>
      </div>
    </div>

    <div v-if="showWinModal" class="modal-overlay">
      <div class="modal-content">
        <h2>恭喜你赢了！</h2>
        <p>你成功合成了2048！</p>
        <button @click="closeWinModal" class="game-button">继续游戏</button>
        <button @click="resetGame" class="game-button">重新开始</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data() {
    return {
      numbers: [],
      positions: [],
      mergedIndices: [],
      showWinModal: false,
      gameStarted: false,
      movingCells: [], // 记录正在移动的方块
      targetPositions: [], // 记录移动目标位置
      transitionDuration: '0.1s' // 动画持续时间
    };
  },
  methods: {
    startGame() {
      this.numbers = this.generateRandomNumbers();
      this.positions = this.generateRandomPositions(this.numbers.length);
      this.gameStarted = true;
      this.showWinModal = false;
      this.movingCells = [];
      this.$nextTick(() => {
        this.$el.querySelector('.game-board').focus();
      });
    },
    resetGame() {
      this.startGame();
    },
    closeWinModal() {
      this.showWinModal = false;
      this.$el.querySelector('.game-board').focus();
    },
    handleKeydown(event) {
      if (!this.gameStarted) return;
      
      switch (event.key) {
        case 'ArrowUp':
          this.move('up');
          break;
        case 'ArrowDown':
          this.move('down');
          break;
        case 'ArrowLeft':
          this.move('left');
          break;
        case 'ArrowRight':
          this.move('right');
          break;
      }
    },
    move(direction) {
      // 重置合并记录
      this.mergedIndices = [];
      this.movingCells = [];
      this.targetPositions = [];
      
      // 创建深拷贝
      const newPositions = JSON.parse(JSON.stringify(this.positions));
      const newNumbers = [...this.numbers];
      
      // 根据方向排序，确保从边缘开始移动
      const indices = [...Array(newPositions.length).keys()];
      indices.sort((a, b) => {
        if (direction === 'up') return newPositions[a].row - newPositions[b].row;
        if (direction === 'down') return newPositions[b].row - newPositions[a].row;
        if (direction === 'left') return newPositions[a].col - newPositions[b].col;
        if (direction === 'right') return newPositions[b].col - newPositions[a].col;
        return 0;
      });
      
      let moved = false;
      indices.forEach(index => {
        const hasMoved = this.moveSingleBlock(index, direction, newPositions, newNumbers);
        moved = moved || hasMoved;
      });

      if (moved) {
        // 设置移动动画
        this.movingCells = [...Array(this.positions.length).keys()];
        this.targetPositions = JSON.parse(JSON.stringify(newPositions));
        
        // 等待动画完成后再更新实际位置
        setTimeout(() => {
          // 过滤掉已合并的方块
          const filteredNumbers = [];
          const filteredPositions = [];
          for (let i = 0; i < newNumbers.length; i++) {
            if (!this.mergedIndices.includes(i)) {
              filteredNumbers.push(newNumbers[i]);
              filteredPositions.push(newPositions[i]);
            }
          }

          this.numbers = filteredNumbers;
          this.positions = filteredPositions;
          this.movingCells = [];

          // 检查是否达到2048
          if (this.numbers.some(num => num === 2048)) {
            this.showWinModal = true;
          }

          // 生成新数字
          this.generateNewNumber();
        }, 100); // 与CSS过渡时间匹配
      }
    },
    moveSingleBlock(index, direction, positions, numbers) {
      if (this.mergedIndices.includes(index)) return false;

      const pos = positions[index];
      let newPos = { ...pos };
      let moved = false;

      if (direction === 'up') {
        for (let row = pos.row - 1; row >= 1; row--) {
          const targetIndex = this.findBlockAt(positions, row, pos.col);
          
          if (targetIndex === -1) {
            newPos.row = row;
            moved = true;
          } else if (numbers[targetIndex] === numbers[index] && 
                    !this.mergedIndices.includes(targetIndex)) {
            // 合并相同数字
            numbers[index] *= 2;
            this.mergedIndices.push(targetIndex);
            newPos.row = row;
            moved = true;
            break;
          } else {
            break;
          }
        }
      } else if (direction === 'down') {
        for (let row = pos.row + 1; row <= 9; row++) {
          const targetIndex = this.findBlockAt(positions, row, pos.col);
          
          if (targetIndex === -1) {
            newPos.row = row;
            moved = true;
          } else if (numbers[targetIndex] === numbers[index] && 
                    !this.mergedIndices.includes(targetIndex)) {
            numbers[index] *= 2;
            this.mergedIndices.push(targetIndex);
            newPos.row = row;
            moved = true;
            break;
          } else {
            break;
          }
        }
      } else if (direction === 'left') {
        for (let col = pos.col - 1; col >= 1; col--) {
          const targetIndex = this.findBlockAt(positions, pos.row, col);
          
          if (targetIndex === -1) {
            newPos.col = col;
            moved = true;
          } else if (numbers[targetIndex] === numbers[index] && 
                    !this.mergedIndices.includes(targetIndex)) {
            numbers[index] *= 2;
            this.mergedIndices.push(targetIndex);
            newPos.col = col;
            moved = true;
            break;
          } else {
            break;
          }
        }
      } else if (direction === 'right') {
        for (let col = pos.col + 1; col <= 9; col++) {
          const targetIndex = this.findBlockAt(positions, pos.row, col);
          
          if (targetIndex === -1) {
            newPos.col = col;
            moved = true;
          } else if (numbers[targetIndex] === numbers[index] && 
                    !this.mergedIndices.includes(targetIndex)) {
            numbers[index] *= 2;
            this.mergedIndices.push(targetIndex);
            newPos.col = col;
            moved = true;
            break;
          } else {
            break;
          }
        }
      }

      positions[index] = newPos;
      return moved;
    },
    findBlockAt(positions, row, col) {
      for (let i = 0; i < positions.length; i++) {
        if (positions[i].row === row && positions[i].col === col && 
            !this.mergedIndices.includes(i)) {
          return i;
        }
      }
      return -1;
    },
    generateNewNumber() {
      if (this.numbers.length >= 81) return;
      
      const newNumber = Math.random() < 0.5 ? 2 : 4;
      const newPositions = this.generateRandomPositions(1, this.positions);
      
      this.numbers.push(newNumber);
      this.positions.push(newPositions[0]);
    },
    generateRandomNumbers() {
      const numbers = [];
      const possibleNumbers = [2, 4];
      for (let i = 0; i < 3; i++) {
        const randomIndex = Math.floor(Math.random() * possibleNumbers.length);
        numbers.push(possibleNumbers[randomIndex]);
      }
      return numbers;
    },
    generateRandomPositions(count, existingPositions = []) {
      const positions = [];
      const usedPositions = new Set(existingPositions.map(pos => `${pos.row}-${pos.col}`));
      while (positions.length < count) {
        const row = Math.floor(Math.random() * 9) + 1;
        const col = Math.floor(Math.random() * 9) + 1;
        const positionKey = `${row}-${col}`;
        if (!usedPositions.has(positionKey)) {
          usedPositions.add(positionKey);
          positions.push({ row, col });
        }
      }
      return positions;
    },
    getCellStyle(index) {
      const style = {
        gridRow: this.positions[index].row,
        gridColumn: this.positions[index].col,
        transition: this.isMoving(index) ? `all ${this.transitionDuration} ease-out` : 'none',
        zIndex: this.isMoving(index) ? 1 : 0
      };
      
      if (this.isMoving(index) && this.targetPositions[index]) {
        // 计算移动距离
        const currentPos = this.positions[index];
        const targetPos = this.targetPositions[index];
        
        if (currentPos.row !== targetPos.row || currentPos.col !== targetPos.col) {
          const rowDiff = targetPos.row - currentPos.row;
          const colDiff = targetPos.col - currentPos.col;
          
          // 使用transform实现平滑移动
          style.transform = `translate(${colDiff * 60}px, ${rowDiff * 60}px)`;
        }
      }
      
      return style;
    },
    isMoving(index) {
      return this.movingCells.includes(index);
    }
  },
  mounted() {
    this.$el.querySelector('.game-board').focus();
  }
}
</script>

<style scoped>
/* 其他样式保持不变... */

.number-cell {
  width: 50px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: bold;
  border-radius: 5px;
  background-color: #eee4da;
  color: #776e65;
  transition: all 0.1s ease-out; /* 添加过渡效果 */
  will-change: transform; /* 优化动画性能 */
}

.number-cell.moving {
  transition: all 0.1s ease-out;
  z-index: 1;
}

/* 新增动态背景样式 */
.dynamic-bg {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  background: linear-gradient(45deg, #ff9a9e, #fad0c4, #fbc2eb, #a6c1ee);
  background-size: 400% 400%;
  animation: gradientBG 15s ease infinite;
}

@keyframes gradientBG {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.game-content {
  background-color: rgba(255, 255, 255, 0.8);
  padding: 20px;
  border-radius: 10px;
  max-width: 900px;
  margin: 0 auto;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
}

.game-controls {
  margin: 20px 0;
}

.game-button {
  padding: 10px 20px;
  margin: 0 10px;
  font-size: 16px;
  background-color: #8f7a66;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  transition: all 0.3s;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.game-button:hover {
  background-color: #9f8b77;
  transform: translateY(-2px);
  box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
}

.game-board-container {
  display: flex;
  justify-content: center;
  margin-top: 20px;
  padding: 5px;
}

.game-board {
  display: grid;
  grid-template-columns: repeat(9, 50px);
  grid-template-rows: repeat(9, 50px);
  grid-gap: 10px;
  background-color: #bbada0;
  outline: none;
  border-radius: 5px;
  padding: 10px;
}

.number-cell {
  width: 50px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  font-weight: bold;
  border-radius: 5px;
  background-color: #eee4da;
  color: #776e65;
  transition: all 0.2s;
}

.number-cell:hover {
  transform: scale(1.05);
}

.number-2 { background-color: #eee4da; }
.number-4 { background-color: #ede0c8; }
.number-8 { background-color: #f2b179; color: white; }
.number-16 { background-color: #f59563; color: white; }
.number-32 { background-color: #f67c5f; color: white; }
.number-64 { background-color: #f65e3b; color: white; }
.number-128 { background-color: #edcf72; color: white; font-size: 20px; }
.number-256 { background-color: #edcc61; color: white; font-size: 20px; }
.number-512 { background-color: #edc850; color: white; font-size: 20px; }
.number-1024 { background-color: #edc53f; color: white; font-size: 16px; }
.number-2048 { background-color: #edc22e; color: white; font-size: 16px; }

/* 胜利弹窗样式 */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background-color: #faf8ef;
  padding: 30px;
  border-radius: 10px;
  text-align: center;
  max-width: 400px;
  width: 80%;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
  animation: modalFadeIn 0.3s ease-out;
}

@keyframes modalFadeIn {
  from {
    opacity: 0;
    transform: translateY(-20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.modal-content h2 {
  color: #776e65;
  margin-bottom: 20px;
}

.modal-content p {
  color: #776e65;
  margin-bottom: 30px;
  font-size: 18px;
}

.modal-content .game-button {
  margin: 0 10px;
}
</style>